package com.google.code.head2head.gwtmodules.server;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

import javax.servlet.ServletException;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.code.head2head.constants.SessionRequestConstants;
import com.google.code.head2head.exceptions.AlreadyRatedException;
import com.google.code.head2head.exceptions.RatingOwnedEntryException;
import com.google.code.head2head.gwtmodules.client.services.FacadeServices;
import com.google.code.head2head.model.Entry;
import com.google.code.head2head.service.EntryService;
import com.google.code.head2head.service.LoginService;
import com.google.code.head2head.util.DtoConverter;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class FacadeServicesImpl extends RemoteServiceServlet implements
		FacadeServices {

	private WebApplicationContext ctx;
	private EntryService entryService;
	private LoginService loginService;

	@Override
	public void init() throws ServletException {
		ctx = WebApplicationContextUtils
				.getWebApplicationContext(getServletContext());
		entryService = (EntryService) ctx.getBean("entryService");
		loginService = (LoginService) ctx.getBean("loginService");
	}

	@SuppressWarnings("unchecked")
	public List getAllEntries(String[] tags) throws Exception {
		List<com.google.code.head2head.model.Entry> allEntries = null;
		if (tags == null) {
			allEntries = entryService.findAll();
		} else {
			allEntries = entryService.findEntriesWithTag(tags);
		}
		List allEntriesDto = new ArrayList();
		for (com.google.code.head2head.model.Entry entry : allEntries) {
			com.google.code.head2head.gwtmodules.client.dto.Entry entryDto = DtoConverter
					.transform(entry);
			allEntriesDto.add(entryDto);
		}

		return allEntriesDto;
	}

	public Long login(String userLogin, String userPassword) {
		Long userId = loginService.authenticate(userLogin, userPassword);
		if (userId != null) {
			getThreadLocalRequest().getSession().setAttribute(
					SessionRequestConstants.USERID.name(), userId);
		}
		return userId;
	}

	public void logout() {
		getThreadLocalRequest().getSession().setAttribute(
				SessionRequestConstants.USERID.name(), null);
	}

	public String rateEntry(Long entryId, int rating) {
		String ip = getThreadLocalRequest().getRemoteAddr();
		try {
			entryService.rateEntry(entryId, (Long) getThreadLocalRequest()
					.getSession().getAttribute(
							SessionRequestConstants.USERID.name()), rating, ip);
			return "User rating " + rating + " was recorded for this entry!";
		} catch (AlreadyRatedException e1) {
			return "Sorry, you have already voted for this entry!!!";
		} catch (RatingOwnedEntryException e2) {
			return "Sorry, you can't vote for your own entry!!!";
		}
	}

	public String addEntryInformations(String title, String keywords) {
		Long entryId = (Long) getThreadLocalRequest().getSession()
				.getAttribute(SessionRequestConstants.ENTRYID.name());
		if (entryId == null) {
			return ("No entry currently in session");
		}
		Entry entry = entryService.getEntry(entryId);
		entry.setTitle(title);
		entry.setTags(new HashSet(Arrays.asList(keywords.split("\\s"))));

		entryService.update(entry);

		return ("Information recorded");
	}

}
